/**
 * GPIO Key Module based on native gpio_key C library.
 * This module provides a singleton interface to GPIO key management.
 * Can be used across threads, but callback registration and loop functions need to be called in the same thread.
 * Features:
 * - Initialize/deinitialize GPIO key monitoring
 * - Query gpiokey status by code
 * - Register gpiokey event callbacks for gpiokey events
 * - Process gpiokey events through event loop
 *
 * Usage:
 * - Call `init()` once to initialize.
 * - Use `getStatus(code)` to query gpiokey status.
 * - Use `setCallbacks()` to register gpiokey event handlers.
 * - Call `loop()` periodically to process events (e.g. in setInterval).
 */
import { gpioKeyClass } from './libvbar-m-dxkey.so'


const dxGpioKey = {};

const gpiokey = new gpioKeyClass();
let _callbacks = {};

/**
 * GPIO key/input event type constant (corresponding to Linux input_ event. type)
 * Used to distinguish the categories of events, such as buttons, coordinates, synchronization, etc.
 * 
 * Reference:<Linux/input-event-codes. h>
 */
dxGpioKey.GPIO_KEY_TYPE = { 
    SYN: 0x00, // Synchronization event (end of event grouping flag)
    KEY: 0x01, // Key event (keyboard, GPIO key, gamepad button)
    REL: 0x02, // Relative position event (mouse, scroll wheel)
    ABS: 0x03, // Absolute position event (touchscreen, joystick)
    MSC: 0x04, // Miscellaneous event (scan code, raw code, etc.)
    SW:  0x05, // Switch event (lid switch, plug/unplug, seat sensor, etc.)
    LED: 0x11, // LED status (e.g. keyboard caps lock indicator)
    SND: 0x12  // Sound event (beeper, etc.)
};

/**
 * Initializes the GPIO key monitoring system.
 * @returns {boolean} True if successful, false otherwise.
 * @example
 * const success = dxGpioKey.init();
 * if (success) {
 *   logger.info('GPIO key initialized successfully');
 * }
 */
dxGpioKey.init = function () {
    return gpiokey.init();
}

/**
 * Deinitializes the GPIO key monitoring system and releases resources.
 * @returns {boolean} True if successful, false otherwise.
 */
dxGpioKey.deinit = function () {
    return gpiokey.deinit();
}

/**
 * Gets the current status of a specific GPIO key.
 * @param {number} code - GPIO key code to query.
 * @returns {KeyEvent} Key status object containing code, type, and value.
 * @typedef {object} KeyEvent
 * @property {number} code - GPIO key code.
 * @property {number} srcCode - GPIO key source code.
 * @property {number} type - Event type (in dxGpioKey.GPIO_KEY_TYPE, e.g. dxGpioKey.GPIO_KEY_TYPE.KEY for key press).
 * @property {number} value - Event value (e.g., 1 for pressed, 0 for released).
 * @example
 * const status = dxGpioKey.getStatus(3) // code in 0-x, is the number of gpiokey hardware interfaces on the device;
 * logger.info(JSON.stringify(status))
 * // Output: { code: 3, srcCode: 33, type: 1, value: 1 }
 */
dxGpioKey.getStatus = function (code) {
    return gpiokey.getStatus(code);
}

/**
 * Sets callback handlers for GPIO key events.
 * @param {object} callbacks - Callback functions.
 * @param {function(KeyEvent)} [callbacks.onKeyEvent] - Called when a key event occurs.
 * @example
 * dxGpioKey.setCallbacks({
 *   onKeyEvent: function(event) {
 *     logger.info('Key event:', JSON.stringify(event));
 *     // Output: Key event: {"code":3,"srcCode":33,"type":1,"value":1}
 *   }
 * });
 * @returns {void}
 */
dxGpioKey.setCallbacks = function (callbacks) {
    _callbacks = callbacks;
}

/**
 * Processes events from the GPIO key event queue. Should be called periodically (e.g. in setInterval).
 * Handles key press/release events and triggers registered callbacks.
 * @example
 * setInterval(() => {
 *   try {
 *     dxGpioKey.loop();
 *   } catch (e) {
 *     logger.error('Error in GPIO key loop:', e);
 *   }
 * }, 50); // Process events every 50ms
 * @returns {void}
 */
dxGpioKey.loop = function () {
    let ev = gpiokey.getEvent();
	if (ev && _callbacks.onKeyEvent) {
		_callbacks.onKeyEvent(ev);
    }
}

/**
 * Gets the native GPIO key object.
 * @returns {Object|null} The native GPIO key object, or null if not initialized.
 */
dxGpioKey.getNative = function () {
    return gpiokey;
}

export default dxGpioKey;